package com.lin.filegraph.utils.comcheck;

import com.lin.filegraph.utils.compdg.ComponentGraph;
import com.lin.filegraph.utils.compdg.ComponentNode;
import com.lin.filegraph.utils.threshold.Threshold;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

/**
 * @description:
 * @author: linhuaixu
 * @time: 2023/5/18 15:50
 */

public class DesignCheck {

    public static void executeCheck(ComponentGraph cgAuto, ComponentGraph cgIn) {
        checkSeparate(cgAuto, cgIn);
        //new OutGraphviz(GraphvizHelper.dotPathTest, GraphvizHelper.outPath, "2", "png").executeCom(cgAuto);
        checkSim(cgAuto, cgIn);
        //new OutGraphviz(GraphvizHelper.dotPathTest, GraphvizHelper.outPath, "3", "png").executeCom(cgAuto);
        checkSame(cgAuto);
    }

    /**
     * 优化独立组件
     */
    private static void checkSeparate(ComponentGraph cgAuto, ComponentGraph cgIn) {
        List<String> comsSeparate = new ArrayList<>();
        List<String> dirsSeparate = new ArrayList<>();
        for (ComponentNode cn : cgAuto.getAllComponents()) {
            // 找到独立组件下的子目录
            if (cgAuto.getPostComponents(cn).size() == 0 && cgAuto.getPreComponents(cn).size() == 0 && cn.getAllFiles().size() == 1) {
                if (cn.getAllFiles().get(0) != null) {
                    dirsSeparate.add(cn.getAllFiles().get(0));
                    comsSeparate.add(cn.getStrComponentName());
                }
            }
        }
        for (ComponentNode cn : cgIn.getAllComponents()) {
            int i = 0;// 记录相同个数
            for (String str : cn.getAllFiles()) {
                if (dirsSeparate.contains(str)) {
                    int j = dirsSeparate.indexOf(str);
                    Collections.swap(dirsSeparate, i, j);
                    Collections.swap(comsSeparate, i, j);
                    i++;
                }
            }
            // 相似度>0.8
            if ((double) i / cn.getAllFiles().size() > Threshold.inputComSep) {
                int len = comsSeparate.size();
                if (i > 1 && len > i) {
                    ComponentNode cn0 = cgAuto.getComponentByName(comsSeparate.get(0));
                    if (cn0 != null) {
                        for (int k = 1; k < i; k++) {
                            ComponentNode cn1 = cgAuto.getComponentByName(comsSeparate.get(k));
                            if (cn1 != null)
                                cgAuto.mergeNodes(cn0, cn1);
                        }
                        cn0.setStrComponentName(cn.getStrComponentName());// 重命名
                    }
                }
            }

        }
    }

    /**
     * 优化组件命名
     */
    private static void checkSim(ComponentGraph cgAuto, ComponentGraph cgIn) {
        // Map<String, Double> comBetween = new HashMap<>();
        System.out.println("**********************");
        System.out.println("打印相似度：");
        for (ComponentNode cnA : cgAuto.getAllComponents()) {
            double simMax = 0;
            String comSim = null;
            for (ComponentNode cnI : cgIn.getAllComponents()) {
                double sim = getSim(cnA, cnI);
                if (sim > simMax) {
                    simMax = sim;
                    comSim = cnI.getStrComponentName();
                }
            }
            if (comSim != null&&!cnA.isFromPre()) {
                System.out.println(cnA.getStrComponentName() + "-" + comSim + ", " + simMax);
                // 相似度超过0.6，重命名
                if (simMax > Threshold.inputComSim) {
                    cnA.setStrComponentName(comSim + cnA.getID());
                }
            }
        }
    }

    /**
     * 同名组件优化
     */
    static void checkSame(ComponentGraph cgAuto) {
        boolean isMerge = false;
        List<ComponentNode> coms = cgAuto.getAllComponents();
        for (int i = 0; i < coms.size(); i++) {
            if (cgAuto.isSeprate(coms.get(i)) && coms.get(i).getAllFiles().size() == 1) {
                ComponentNode cnMax = coms.get(i);
                String str1 = coms.get(i).getStrComponentName().replaceAll("[^a-zA-Z]", "");
                System.out.println(cnMax.getStrComponentName()+"-"+cnMax.getAllFiles().get(0)+"##");
                for (int j = 0; j < coms.size(); j++) {
                    if (j != i&&!coms.get(j).getStrComponentName().matches("/d+")) {
                        String str2 = coms.get(j).getStrComponentName().replaceAll("[^a-zA-Z]", "");
                        if (str2.equals(str1) && coms.get(j).getAllFiles().size() > cnMax.getAllFiles().size()) {
                            cnMax = coms.get(j);
                        }
                    }
                }
                if(!cnMax.equals(coms.get(i))){
                    cgAuto.mergeNodes(cnMax, coms.get(i));
                    isMerge=true;
                    break;
                }
            }
        }
        if(isMerge)
            checkSame(cgAuto);
    }

    /**
     * 计算组件相似度
     */
    private static double getSim(ComponentNode cnA, ComponentNode cnI) {
        int same = 0;
        double sim = 0;
        for (String s : cnA.getAllFiles()) {
            if (cnI.getAllFiles().contains(s))
                same++;
        }
        sim = (double) same / (cnA.getAllFiles().size());
        return sim;
    }
    //partitionedCompDG---文件图
    public static void CombineArcDocument(ComponentGraph partitionedCompDG, ComponentGraph excelgraph) {
        // TODO Auto-generated method stub
        List<ComponentNode>components=excelgraph.getAllComponents();
        CombineArcDocumentDetail(partitionedCompDG,components,0);
    }
    //compnents是excel里的组件
    private static void CombineArcDocumentDetail(ComponentGraph partitionedCompDG, List<ComponentNode> components,
                                                 int i) {
        // TODO Auto-generated method stub
        if(i==components.size())
            return;
        ComponentNode cnode=components.get(i);
        List<String>files=cnode.getAllFiles();
        if(files.size()<=1)
            CombineArcDocumentDetail(partitionedCompDG,components,i+1);
        else {
            List<ComponentNode>NeedCombineComps=CombineComponent(files,partitionedCompDG);
            if(NeedCombineComps.size()>1)
                partitionedCompDG.mergeNodes(NeedCombineComps);
            CombineArcDocumentDetail(partitionedCompDG,components,i+1);
        }
    }

    private static List<ComponentNode> CombineComponent(List<String> files, ComponentGraph partitionedCompDG) {
        // TODO Auto-generated method stub
        List<ComponentNode>NeedCombineComps=new LinkedList<ComponentNode>();
        List<ComponentNode>file_components=partitionedCompDG.getAllComponents();
        for(String file :files)
            for(ComponentNode cn:file_components) {
                if(cn.getAllFiles().contains(file)) {
//				如果excel提供的组件中file与架构恢复中的feature组件相似即终止该组件中的架构文档帮助
                    if(cn.isFeature())
                        return NeedCombineComps;
                    NeedCombineComps.add(cn);
                    break;
                }
            }
        return NeedCombineComps;
    }
}

